package com.wjy.myokhttp.net;

import com.google.gson.JsonObject;

import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

import io.reactivex.Observable;

import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.HTTP;
import retrofit2.http.Headers;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
import retrofit2.http.PartMap;
import retrofit2.http.Path;
import retrofit2.http.Query;
import retrofit2.http.QueryMap;
import retrofit2.http.Streaming;
import retrofit2.http.Url;

/**
 * Created by wjy.
 * Date: 2019/11/22
 * Time: 11:42
 * Describe: 定义接口：管理Retrofit的各种数据请求(post、get)，包含请求api、请求参数
 */
public interface ApiService {

    //login_rid=100d8559092c7ef7d5a
//    String BASE_URL = "http://36.112.137.125:20204/";//服务器地址

    String BASE_URL = "http://server.fs.nrynr.com/ApiPhoneControls.ashx/";

    //Observable<JsonObject>  中的JsonObject可以换成对应的实体类

    /**
     * GET后面的url中可以使用自定义的变量，如 {index}、{id}进行占位 ，并使用 @Path("index") 、@Path("id") 注解为 {index} 、{id} 提供值
     * 注意:形如“?page/xxx/id/aaa”才【能】使用@Path来拼接url
     *     形如“?a=xxxx&b=xxxx&c=xxxx”的url是【不能】用@Path注解来拼接的，应该使用@Query或者@QueryMap注解
     *     @GET("?app=weather.future&weaid=1&&appkey={key}")
     * @param index
     * @param id
     * @return
     */
    @GET("page/{index}/id/{id}")
    Observable<JsonObject> requestWeather(@Path("key") int index, @Path("id") int id);

    //@Query和@QueryMap注解会把参数拼接到url后面，适用于GET请求

    //键值对形式
    @GET("?")
    Observable<JsonObject> requestWeather(@Query("app") String app,@Query("appkey") int appkey);

    //Map形式
    @GET("?")
    Observable<JsonObject> requestWeather(@QueryMap Map<String,String> params);

    //List列表形式
    @GET("?")
    Observable<JsonObject> requestWeather(@QueryMap List<String> stringList);

    //url形式
    @GET
    Observable<JsonObject> requestWeather(@Url String url);

    //无请求参数形式
    @GET("?")
    Observable<JsonObject> requestWeather();

    //==============================以上为GET请求方式===========================//


    //==============================以下为POST请求方式===========================//
    /**
     * @Field或@FieldMap做表单提交,适用于POST请求;对应POST请求，需要结合@FormUrlEncoded来使用
     * @Body会将请求参数放到请求体中，所以适用于POST请求
     * @Body标签不能和@FormUrlEncoded或@Multipart标签同时使用，会报错
     * @return
     */
    @FormUrlEncoded
    @POST("/")
    Observable<JsonObject> requestWeathers(@Field("app") String app,@Field("appkey") int appkey);

    @FormUrlEncoded
    @POST("/")
    Observable<JsonObject> requestWeathers(@FieldMap Map<String,String> params);

    /**
     * @Body实际上是将类转换成json实体作为请求体来请求网络的
     * 使用这个标签的意思是我们可以定义个实体类来封装参数，作为请求参数
     * @Body标签不能和@FormUrlEncoded或@Multipart标签同时使用，会报错
     * @param params
     * @return
     */
    @POST("/")
    Observable<JsonObject> requestWeathers(@Body RequestParams params);
    class RequestParams{
        String app;
        int appkey;
    }

    //==============================以下为HTTP请求方式===========================//
    /**
     * @HTTP请求，可配置成以上几种中的任意一种,下面就分别以一种形式来举例
     */
    //@HTTP配置get请求
    @HTTP(method = "GET", path = "?app=weather.future&&appkey=10003", hasBody = false)
    Observable<JsonObject> requestWeather1(@Query("app") String app,@Query("appkey") int appkey);

    //@HTTP配置post请求
    //1.配置POST请求必须结合@FormUrlEncoded使用，否者会报错
    //2.hasBody必须配置为true，否则报错
    @FormUrlEncoded
    @HTTP(method = "POST", path = "?", hasBody = true)
    Observable<JsonObject> requestWeather2(@Field("app") String app,@Field("appkey") int appkey);

    //==============================@Multipart 主要是与@POST结合使用做文件的上传===========================//
    @Multipart
    @POST("/")
    Observable<ResponseBody> uploadFile(@Part("description") RequestBody description, @Part MultipartBody.Part file);

    @Multipart
    @POST("/")
    Observable<ResponseBody> uploadFile(@PartMap Map<String, RequestBody> params);

    //==============================@Streaming 主要做大文件下载===========================//
    @GET
    @Streaming
    Observable<ResponseBody> downloadImage(@Url String url);


    //==============================以下为使用 Call 上传图片的几种写法===========================//
    /**
     * 上传图文
     * @param description
     * @param file
     * @return
     */
    @Multipart
    @POST("web/shrink")
    Call<ResponseBody> uploadFile1(@Part("description") RequestBody description, @Part MultipartBody.Part file);

    /**
     * 上传一张图片
     * @param file
     * @return
     */
    @Multipart
    @POST("web/shrink")
    Call<ResponseBody> uploadFile2(@Part() RequestBody file);

    /**
     * 上传一张图片 另一种写法
     * @param file
     * @return
     */
    @Multipart
    @POST()
    Call<ResponseBody> uploadFile3(@Url String url, @Part() RequestBody file);

    /**
     * 上传数量确定的多张图片
     * @param description
     * @param img1
     * @param img2
     * @param img3
     * @return
     */
    @POST("web/shrink")
    Call<ResponseBody> uploadFiles4(@Part("filename") String description,
                                   @Part("img\"; name=\"img1.png") RequestBody img1,
                                   @Part("img\"; name=\"img2.png") RequestBody img2,
                                   @Part("img\"; name=\"img3.png") RequestBody img3);

    /**
     * 上报数量不定的多张图片 版本1
     * @param params
     * @return
     */
    @Multipart
    @POST("web/shrink")
    Call<ResponseBody> uploadFile5(@PartMap Map<String, RequestBody> params);

    /**
     * 上报数量不定的多张图片 版本2
     * @param url
     * @param maps
     * @return
     */
    @Multipart
    @POST("web/shrink")
    Call<ResponseBody> uploadFile6( @Url String url, @PartMap() Map<String, RequestBody> maps);

    //&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&以上为常用请求方式的参考示例&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//

    //下面写几个使用测试用例
    //Url形式
    @GET
    Observable<JsonObject> requestData(@Url String url);

    //键值对形式
    @GET("?s=Platform.User.Login")
    Observable<JsonObject> requestLogin_get(@Query("username")String username,@Query("pwd") String pwd,@Query("regid") String regid);

    @POST("/?s=Platform.User.Login")
    @FormUrlEncoded
    Observable<JsonObject> requestLogin_post(@Field("username") String username,@Field("pwd") String pwd,@Field("regid") String regid);

    //GET请求的Map形式
    @GET("?s=Platform.User.Login")
    Observable<JsonObject> requestLogin_get_map(@QueryMap Map<String,String> params);

    //POST请求的Map形式
    @FormUrlEncoded
    @POST("/?s=Platform.User.Login")
    Observable<JsonObject> requestLogin_post_map(@FieldMap Map<String,String> params);

    //@Body实际上是将类转换成json实体作为请求体来请求网络,目前没找到可以接受json格式的请求体作为参数的网络，因此这里这是从形式说明怎么使用，这是没有问题
    @POST("/?s=Platform.User.Login")
    Observable<JsonObject> requestLogin_post_body(@Body LoginInfo loginInfo);
    class LoginInfo{
        public String username;
        public String pwd;
        public String regid;
    }

    //@HTTP配置get请求
    @HTTP(method = "GET", path = "?s=Platform.User.Login", hasBody = false)
    Observable<JsonObject> requestLogin_get_http(@Query("username") String username,@Query("pwd") String pwd,@Query("regid") String regid);

    //@HTTP配置post请求
    //1.配置POST请求必须结合@FormUrlEncoded使用，否者会报错
    //2.hasBody必须配置为true，否则报错
    @FormUrlEncoded
    @HTTP(method = "POST", path = "/?s=Platform.User.Login", hasBody = true)
    Observable<JsonObject> requestLogin_post_http(@Field("username") String username,@Field("pwd") String pwd,@Field("regid") String regid);

    /**
     * 上传一张图片
     */
    @POST("/?s=Platform.UpImg.Img")
    @FormUrlEncoded
    Observable<JsonObject> uploadImage(@Field("tp") String tp,@Field("code") String code);


    @Headers("Content-Type: application/json")
    @POST("/")
    Observable<JsonObject> requestTest(@Body HandlerModel handlerModel);
    class HandlerModel{
        public String Action;
        public Object[] Param;
    }

    @FormUrlEncoded
    @POST("/")
    Observable<JsonObject> requestTest(@Field("Json") String Json);
}
